package com.bclz.netty.start;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;


public class NettyTest {

    public static void main(String[] args) {
        /**
         * 创建 BossGroup 和 WorkerGroup
         * 1. 创建两个线程组 bossGroup 和 workerGroup
         * 2. bossGroup 只是处理连接请求 , 真正的和客户端业务处理， 会交给 workerGroup 完成
         * 3. 两个都是无限循环
         * 4. bossGroup 和 workerGroup 含有的子线程(NioEventLoop)的个数
         *  默认线程数: 源码DEFAULT_EVENT_LOOP_THREADS = Math.max(1, SystemPropertyUtil.getInt(
         *                 "io.netty.eventLoopThreads", Runtime.getRuntime().availableProcessors() * 2));
         * */
        EventLoopGroup bossGroup=new NioEventLoopGroup(1);
        EventLoopGroup workGroup=new NioEventLoopGroup();


        try {
            ServerBootstrap serverBootstrap=new ServerBootstrap();
            serverBootstrap.group(bossGroup,workGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new LoggingHandler(LogLevel.INFO));
                            //websocket协议本身是基于http协议的，所以这边也要使用http解编码器
                            pipeline.addLast(new HttpServerCodec());

                            //以块的方式来写的处理器
//                            pipeline.addLast(new ChunkedWriteHandler());
                            //netty是基于分段请求的，HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度
                            pipeline.addLast(new HttpObjectAggregator(1024*1024*1024));
                            //ws://server:port/context_path
                            //ws://localhost:9999/ws
                            //参数指的是contex_path
//                            pipeline.addLast(new WebSocketServerProtocolHandler("/ws",null,true,65535));
                            pipeline.addLast(new NettyServerHandle());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG,128)           //等待连接请求队列的大小
                    .childOption(ChannelOption.SO_KEEPALIVE,true);  //保存活动连接，由于TCP默认不发送心跳,设置后长时间(TCP默认2小时发送KEEPALIVE)无数据，会发送测试报文
            ChannelFuture channelFuture = serverBootstrap.bind(6666).sync();
            System.out.println("wait client connect！！！");
            channelFuture.addListener(future->{ //绑定端口channelFuture添加监听事件

                if(future.isSuccess()){
                    System.out.println("server listen 6666 port success...");
                }else {
                    System.out.println("server listen 6666 port fail...:");
                }

            });
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            System.err.println("NETTY SERVER EXCEPTION！！！"+e);
        }finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

    }

    private static class ClientTest{


        public static void main(String[] args) {

            EventLoopGroup workGroup=new NioEventLoopGroup();

            try {
                Bootstrap bootstrap=new Bootstrap();
                bootstrap.group(workGroup)
                        .channel(NioSocketChannel.class)
                        .handler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            protected void initChannel(SocketChannel ch) throws Exception {
                                ch.pipeline().addLast(new NettyClientHandle());
                            }
                        });
                ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6666).sync();
                channelFuture.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                System.err.println("NETTY CLIENT EXCEPTION ！！！");
            }finally {
                workGroup.shutdownGracefully();
            }

        }



    }

}
